//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
# include "config.h"

#define SPL_RAM_ADDRESS         0xA3C00000
#define MDOCPBaseAddress        0x00000000
#define SPL_SIZE                0x400
#define SPL_SIGN                0x544F4F42
#define CDSN_IO     0x0800
#define CDSN_IO_CORR     0x02
#define CDSN_CNTR     0x1000
#define MDOCPBaseAddressIO      (MDOCPBaseAddress + CDSN_IO)
#define MDOCPBaseAddressCNTR    (MDOCPBaseAddress + CDSN_CNTR)
#define G3_NNOPreg     0x3E
#define G3_NDOCcontrol     0x0C
#define G3_NDOCcontrolConfirm     0x72
#define G3_NdeviceSelect     0x0A
#define G3_NflashSequence     0x32
#define G3_NflashCommand     0x34
#define G3_NflashDataEnd     0x1E
#define G3_NflashAddress     0x36
#define G3_NflashControl     0x38
#define G3_NECCcontrol_0     0x40
#define G3_NECCcontrol_1     0x42
#define G3_NreadAddrReg     0x1A
#define G3_EDC_ERROR_MASK     0x80
#define G3_EDC_VAL     0x8A0F
#define RESET_FLASH_CMD     0xFF
#define READ_A_FLASH_CMD     0x0
#define READ_C_FLASH_CMD     0x50
#define SLC_MODE_CMD         0xA2
#define RELIABLE_SLC_MODE_CMD  0x22
#define FAST_MODE_CMD     0xA2
#define RELIABLE_MODE_CMD     0x22
#define AUTO_PAGE_INC_CMD     0xB3
#define READ_CMD     0x60
#define MULTI_READ_CMD     0x30
#define REGISTER_READ_CMD     0xE0
#define ADDR_INPUT_FOR_REG_READ     0x05
#define G3_PLANE_0     0x00
#define G3_PLANE_1     0x40
#define ResetFlash_Seq     0
#define READ_A_Seq     14
#define READ_C_Seq     16
#define SLC_MODE_Seq           9
#define FAST_MODE_Seq     9
#define AUTO_PAGE_INC_Seq     12
#define READ_Seq     18
#define IPL_MAX_ID     0x30
#define G3_RB_SHIFT     31
#define G3_CDSN_CE     0x39
#define G3_ACCESS_ERR     0x06
#define DOC_CTRL_NORMAL_MODE     0x05

#define BLOCK_DATA     0x200
#define DUMMY_DATA     10
#define G3_EDC_DATA     16
#define G3_PAGE_OFFSET          0x84
#define G3_SIGN_OFFSET          0x80
#define END_SPL_ADDR     0x1000/2
#define G3_SPL_NEXT             0x80
#define SPL_START               0x80
#define MDOC32_ID     0x40
#define MDOC512_ID     0x20
#define G3_PAGES_IN_UNIT     0x40

#define BAUD_4800    0xC0 @  UART Divisor low bye setting for 4800 baud
#define BAUD_9600    0x60 @  UART Divisor low bye setting for 9600 baud
#define BAUD_19200   0X30 @  UART Divisor low bye setting for 19200 baud
#define BAUD_38400   0x18 @  UART Divisor low bye setting for 38400 baud
#define BAUD_57600   0x10 @  UART Divisor low bye setting for 57600 baud
#define BAUD_115200  0X08 @  UART Divisor low bye setting for 115200 baud


#define TDRQ     0x20   @  Transmit Data Request
#define TEMT     0x40	@  Transmitter Empty bit
#define DR       0x01	@  Data Ready bit
#define DLAB     0x80   @  DLAB bit
#define nBT_OFF  0x100  @  BTUART Tranceiver Control Bit
#define BTDTR    0x80 	@  BTUART Data Terminal Ready bit


.text
	/* Jump vector table as in table 3.1 in [1] */
.globl _start
_start:	b	reset
	b	undefined_instruction
	b	software_interrupt
	b	abort_prefetch
	b	abort_data
	b	not_used
	b	irq
	b	fiq

reset:
	 mov	r0, #0x13	// set into Supervisior mode
	 orr	r0, r0, #0xC0	// disable IRQ, FIQ
	 msr	cpsr, r0

	 bl	Init_GPIO

	 bl	Init_INT
//The following is added by Bill Chen
	ldr     r0,  =PWR_BASE_PHYSICAL
	ldr     r10, [r0, #RCSR_OFFSET]
	mov     r2,  #RCSR_ALL		// Mask RCSR
	and     r10,  r10,  r2		// r10 now holds the conditioned Reset Reason
	teq     r10, #RCSR_SLEEP_RESET
	beq     7f
//
	 bl     Init_Clocks

7:
	 bl     Init_Uart

	 mov	r2, #0x61
	 bl	UartPrintch

	 bl     Init_Mem

	 mov	r2, #0x62
	 bl	UartPrintch

	 bl	mdoc_copy





/* #endif */

RAMBEGIN:

	mov	r2, #0x31
	bl	UartPrintch

	@adr     r3,  str_cpspl   @ FRQ Interrupt Mesage
	@bl      UartPrintStr


		/* Set up the user and irq stack pointer */
	ldr r1, =M_START
	ldr r2, =M_STACK_END_OFFSET_FROM_RAM_START
	add r1, r1, r2
	sub sp, r1, #0x1000 /* set IRQ sp : 0x100 bytes lower from the IRQ sp */
			/* If you need more stack space in interrupt, you can increase this value (0x100) to much as you want */

	/* Jump to the C code */
	/* from here, copy the main code from flash to RAM.
	 * interrupt vector contents should be changed,
	 * as they use bl or other method for communication
	 * this code should be modified to jump to #0xc?????
	 * as we need to jump from flash to RAM
	 */
	/* check copy from 16 bits to 32 bits */

	/* copy data from the flash to ram */
	/*
	 *       Flash 16MBx16bits (32MB)       SDRAM 16MBx16bits (32MB)
	 *       +----------+               r9->+----------+
	 *       |          |                   |   Stack  |
	 *       |          |               r8->|..........|
	 *       |          |                   |          |
	 *       |          |                   |BootLoader|
	 *       |          |                   |          |
	 *       |          |         r6,r7(1)->|..........|
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |          |                   |          |
	 *       |----------| --                |          |
	 *       |          | /\                |          |
	 *       |BootLoader| ||                |          |
	 *       |          | \/                |          |
	 *       +----------+ --         r7(0)->+----------+
	 *
	 */
		/* clear the BSS section */
	ldr	r1, bss_start
	ldr	r0, bss_end
	sub	r0, r0, r1

	/* r1 = start address */
	/* r0 = *number of bytes */
	mov	r2, #0
	mov 	r3, #0
	mov	r4, #0
	mov	r5, #0

clear_bss:
	stmia	r1!, {r2,r3,r4,r5}
	subs	r0, r0, #16
	bne	clear_bss

	mov	r2, #0x32
	bl	UartPrintch

	bl	c_main

	/* The c code should never return ! */
	b	reset


infinite_loop:
	b infinite_loop

undefined_instruction:
	b	undefined_instruction

software_interrupt:
	b	software_interrupt

abort_prefetch:
	b	abort_prefetch

abort_data:
	b	abort_data

not_used:
	b	not_used

irq:
	sub lr, lr, #4
	ldr sp, =M_STACK_END_OFFSET_FROM_RAM_START
	add sp, sp, #RAM_START	/* I cannot load the value to other register */
				/* so #RAM_START is still restricted */
	stmfd sp!, {r0-r12,lr}

	ldr r1, =M_START
	ldr r2, =M_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START
	add r1, r1, r2
	add pc, pc, r1 /* now jump to ram */
	mov r1, r1 /* pc advances 2 instructions further */
	mov r1, r1
	mov r1, r1
	bl	c_irq
	ldmfd sp!, {r0-r12,pc}^

fiq:
	b	fiq


@If system boot from MDOC,do nessary mdoc init within the bound of 2k binary code size

@=========================================================================
@   IPL example code - ARM 32
@
@  Sequence:
@    1. Check type of Reset: (to be added by customer)
@         (Hard Reset, Soft Reset, Sleep / Resume Reset, WatchDog Reset)
@    2. In case of Soft or Sleep / Resume Reset Jump to specific RAM location,
@         in case of Hard or WatchDog Reset Continue IPL Steps
@    3. Minimal H/W Init: (to be added by customer)
@         (Set phase-locked loop (PLL) in PPCR, Setup all nesessary CSx lines)
@    4. Enable system RAM: (to be added by customer)
@         (Init Memory Controller)
@    5. Copy IPL To System RAM
@    6. Jump to IPL code in RAM
@    7. Copy SPL code from DiskOnChip Flash to system RAM
@    8. Jump to SPL code for further system initialization and loading
@
@  Note:
@    The code should NOT be used with DOC2000, DOC 2000 TSOP and MDOC
@
@  TODO#:
@    1. Define Features: SPL_MODE, etc...
@    2. Define your MDOC+ window relevant address bits
@    3. Define your System RAM loacation for storing IPL and SPL code
@    4. Set your SPL size (default is 16 Kbytes)
@    5. Set SPL signature (default is BIPO)
@    6. Insert your chipset IPL code (system initialization sequence (1) - (4))
@

@=========================================================================



@===============================================================
@ TODO #1 - Define Features
@===============================================================


mdoc_copy:


@---------------------------------------------------------------
@ 1. Setup destination before copying SPL and Size
@---------------------------------------------------------------
        mov     r11, #SPL_SIZE          @ Get SPL Size
        ldr     r12, =SPL_RAM_ADDRESS   @ Get SPL Address
@---------------------------------------------------------------
@ 2. Init pointers to CDSN_IO and CDSN_CONTROL area
@       mov     r1, #CDSN_IO      @ pointer to CDSN_IO (offset 0x800)
@---------------------------------------------------------------
    @ set DiskOnChip window
        ldr     r1, =MDOCPBaseAddressCNTR
@----- Registers Usage: ----------------------------------------
@ r0  - temp0
@ r1  - temp1 - CDSN_IO (offset 0x800) and CDSN_CNTR (offset 0x1000)
@ r2  - temp2
@ r3  - current page pointer (page address)
@ r4  - page counter
@ r5  - temp3 - offset for CDSN_CNTR
@ r6  - functions parameter 1
@ r7  - temp4 - functions parameter 2
@ r8  - page offset
@ r9  - page in unit mask
@ r10 - return address
@ r11 - SPL Size
@ r12 - pointer to SPL in RAM
@---------------------------------------------------------------
G3_start_of_ipl_copy:
@---------------------------------------------------------------
@ 3. Load SPL starting address (address is in Flash)
@---------------------------------------------------------------
        mov     r3, #(SPL_START << 2)
        mov     r9, #((G3_PAGES_IN_UNIT - 1) >> 1)
        mov     r4, #1
@---------------------------------------------------------------
@ 4. Get Asic ready
@---------------------------------------------------------------
        ldrb    r2, [r1, #G3_NDOCcontrol]   @ First Time Access
        mov     r2, #DOC_CTRL_NORMAL_MODE
        strb    r2, [r1, #G3_NDOCcontrol]
        mvn     r2, r2                      @ move NOT
        strb    r2, [r1, #G3_NDOCcontrolConfirm]
        strh    r1, [r1, #G3_NreadAddrReg]  @ write NchipId addr to addr-reg
        ldrh    r2, [r1]                    @ Read chip ID.
        cmp     r2, #(MDOC512_ID << 4)
        bne     NoDocFound
	strb    r1, [r1, #G3_NdeviceSelect] @ Set Floor 0
        mov     r0, #G3_CDSN_CE             @ set WP | CE
        strb    r0, [r1, #G3_NflashControl]
@---------------------------------------------------------------
@ 5. Look for SPL start
@---------------------------------------------------------------
G3_FindNextUnit:
    @ Clean Access Error
        mov     r7, #ResetFlash_Seq         @ Reset Sequence
        mov     r6, #RESET_FLASH_CMD        @ Reset Command
        bl      G3_SendCommandAndSeq
        bl      G3_WaitForReady
        strb    r0, [r1, #G3_NNOPreg]       @ NOP

    @ Set SLC Mode
        mov     r7, #SLC_MODE_Seq           @ SLC Mode Sequence
        mov     r6, #SLC_MODE_CMD           @ SLC Mode Command
        bl      G3_SendCommandAndSeq
        mov     r6, #RELIABLE_SLC_MODE_CMD
        bl      G3_SendCommand

G3_continue_search:
        add     r3, r3, #G3_SPL_NEXT
    @ Read Signature
        bl      G3_ReadCommandInit

    @ Check For Protection Error
        add     r7, r1, #G3_NflashControl
        strh    r7, [r1, #G3_NreadAddrReg]
        ldrb    r0, [r7]
        tst     r0, #G3_ACCESS_ERR
        bne     G3_FindNextUnit @ skip unit in case of protection violation

    @ Set Signatue Offset
        mov     r8, #G3_SIGN_OFFSET
        bl      G3_ReadCommandContinue
        ldr     r6, =SPL_SIGN
    @ Reading from CDSN IO - 4 bytes of data (signature)
        ldrh    r0, [r7, #CDSN_IO_CORR]
        ldrh    r2, [r7, #CDSN_IO_CORR]
        strb    r1, [r1, #G3_NflashDataEnd] @ Finish Read Sequence
        strb    r0, [r1, #G3_NNOPreg]       @ NOP
        strb    r0, [r1, #G3_NNOPreg]
        orr     r0, r0, r2, LSL #16
        cmp     r6, r0
        bne     G3_continue_search
@---------------------------------------------------------------
@ 7. Issue READ command
@---------------------------------------------------------------
G3_Read_A_Area_start:
@ Set Page Offset 0
        eor     r8,r8,r8
        b       G3_Read_start
G3_Read_B_Area_start:
@ Set Page Offset 0x84
        mov     r8, #G3_PAGE_OFFSET
G3_Read_start:
        bl      G3_ReadCommandInit
        bl      G3_ReadCommandContinue
@---------------------------------------------------------------
@ 8. Read first 512 bytes
@---------------------------------------------------------------
    @ Init amount of data to read
        mov     r0, #BLOCK_DATA
        add     r0, r0, #G3_EDC_DATA
    @ Read 512 bytes of data + 8 bytes Signature + 7 bytes of EDC + 1
G3_Read_first_512bytes:
        ldrh    r5, [r7, #CDSN_IO_CORR]     @   r5  <-- [r7+2]
        strh    r5, [r12], #2               @ [r12] <-- r5, r12+=2
        subs    r0, r0, #2
        bne     G3_Read_first_512bytes

        strb    r1, [r1, #G3_NflashDataEnd] @ Finish Read Sequence
        strb    r0, [r1, #G3_NNOPreg]
        strb    r0, [r1, #G3_NNOPreg]
    @ Check if even or odd page is read
        cmp     r8, #0
    @ EDC mode is applied only to even page
        bne     G3_NoEdcErrorA
        mov     r8, #1
        add     r0, r1, #G3_NECCcontrol_1
        strh    r0, [r1, #G3_NreadAddrReg]
        ldrb    r0, [r0]
        tst     r0, #G3_EDC_ERROR_MASK
        beq     G3_NoEdcErrorA
        sub     r12, r12, #BLOCK_DATA
        sub     r8, r8, #1
G3_NoEdcErrorA:
        sub     r12, r12, #G3_EDC_DATA      @ Restore r12 to SPL Addr
        cmp     r8, #0
        beq     G3_Read_B_Area_start        @ EDC Error
@---------------------------------------------------------------
@ 9. Check if SPL is already copied
@---------------------------------------------------------------
G3_read_Next:
        cmp     r4, r11
        beq     JumpToSPL
        @IF SPL_MODE
        add     r3, r3, #2
        @ELSE
        @add     r3, r3, #1                  @ page address
        @ENDIF @ SPL_MODE
    @ Put into r0 exact number of pages that was read in current unit
        and     r0, r9, r4                  @ R0 <- R4 & #(PAGES_IN_UNIT - 1)
        add     r4, r4, #1                  @ page counter
        cmp     r0, #0
        bne     G3_Read_A_Area_start        @ read in current unit
        sub     r3, r3, #G3_PAGES_IN_UNIT   @ will be incremented later
        b       G3_FindNextUnit             @ goto next unit
@---------------------------------------------------------------
@ 10. Branch to SPL located in system RAM for further initialization
@---------------------------------------------------------------
NoDocFound:

	b .

@        mov     r0, #FALSE
@        b       ReturnToCaller
JumpToSPL:

@        mov     r0, #TRUE
ReturnToCaller:

		ldr	r1, =RAMBEGIN
		@ldr	r2, =SPL_RAM_ADDRESS
		@add	r1, r1, r2
		mov	pc, r1
@        ldr     pc, =SPL_RAM_ADDRESS


@===============================================================
@       Send Read Command Init
@       On Entry: Nothing
@       On exit: r6, r7, r10 destroyed
@===============================================================
G3_ReadCommandInit:
        mov     r10, lr
        mov     r7, #READ_A_Seq             @ Select Area A Command
        mov     r6, #READ_A_FLASH_CMD
        bl      G3_SendCommandAndSeq
        mov     r7, #READ_Seq               @ Read Command to Plane 0
        mov     r6, #READ_CMD
        bl      G3_SendCommandAndSeq

        mov     r6, #G3_PLANE_0             @ Address to Plane 0
        bl      G3_SendAddress
        mov     r6, #READ_CMD               @ Read Command to Plane 1
        bl      G3_SendCommand
        mov     r6, #G3_PLANE_1             @ Address to Plane 1
        bl      G3_SendAddress
        mov     pc, r10
@===============================================================
@       Send Read Command Continue
@       On Entry: r8 = Page Offset
@       On exit:  r7 -> 0x800, r6, r10 destroyed
@===============================================================
G3_ReadCommandContinue:
        mov     r10, lr
        mov     r6, #MULTI_READ_CMD
        bl      G3_SendCommand
        bl      G3_WaitForReady
        mov     r6, #ADDR_INPUT_FOR_REG_READ
        bl      G3_SendCommand

        strb    r8, [r1, #G3_NflashAddress] @ r8[0..7]   -->  0..7
        strb    r8, [r1, #G3_NNOPreg]

        mov     r6, #REGISTER_READ_CMD
        bl      G3_SendCommand

        bl      G3_SetEdcMode

        ldr     r7, =MDOCPBaseAddressIO     @ r7 <- 0x800
        strh    r7, [r1, #G3_NreadAddrReg]
        mov     pc, r10
@===============================================================
@       Set EDC Mode for 512 + 15 data
@       On Entry: Nothing
@       On exit: r6 destroyed
@===============================================================
G3_SetEdcMode:
        ldr     r6, =G3_EDC_VAL
        strh    r6, [r1, #G3_NECCcontrol_0]
    @ 5 NOPs
        strb    r6, [r1, #G3_NNOPreg]
        strb    r6, [r1, #G3_NNOPreg]
        strb    r6, [r1, #G3_NNOPreg]
        strb    r6, [r1, #G3_NNOPreg]
        strb    r6, [r1, #G3_NNOPreg]
        mov     pc, lr
@===============================================================
@       Send Command and Sequence
@       On Entry: r6 = Type of Command, r7 = Type of Sequence
@       On exit: r5 destroyed
@===============================================================
G3_SendCommandAndSeq:
        strb    r7, [r1, #G3_NflashSequence]@ Send Sequence
G3_SendCommand:
        strb    r6, [r1, #G3_NflashCommand] @ Send Command
        strb    r6, [r1, #G3_NNOPreg]
        strb    r6, [r1, #G3_NNOPreg]
        mov     pc, lr
@===============================================================
@       Send Address
@       On Entry: r6 = Plane: 0 or 1
@                 r3 = Address on flash in pages
@       On exit: r0 destroyed
@===============================================================
G3_SendAddress:
        orr     r0, r3, r6                  @ Set Plane: 0 or 1
        strb    r0, [r1, #G3_NflashAddress] @ r3[0..7]   -->  9..16
        mov     r0, r0, LSR #8
        strb    r0, [r1, #G3_NflashAddress] @ r3[8..15]  -->  17..24
        mov     r0, r0, LSR #8
        strb    r0, [r1, #G3_NflashAddress] @ r3[16..23] -->  25..27
    @ Address Pipe Term
        strb    r0, [r1, #G3_NNOPreg]
        mov     pc, lr
@===============================================================
@       WaitForReady
@       On exit: r0, r7 destroyed
@===============================================================
G3_WaitForReady:
    @ 4 NOPs
        strb    r0, [r1, #G3_NNOPreg]
        strb    r0, [r1, #G3_NNOPreg]
        strb    r0, [r1, #G3_NNOPreg]
        strb    r0, [r1, #G3_NNOPreg]
    @ Wait For Ready - wait untill (value & 0x01) equals to 0x01
        add     r7, r1, #G3_NflashControl
        strh    r7, [r1, #G3_NreadAddrReg]
G3_WaitForReadyLoop:
        ldrb    r0, [r7]
        movs    r0, r0, LSL #G3_RB_SHIFT
        beq     G3_WaitForReadyLoop

        mov     pc, lr



Init_Uart:

	ldr    r0,  = STUART_BASE_PHYSICAL @ use BTUART for debug port
	mov    r2,  #0x08	           @ set baudrate 115200

	mov    r1,  #0x0	           @ Zero out a work register
	str    r1,  [r0, #ST_IER_OFFSET]   @ Zero out Interrupt Enable Register
	str    r1,  [r0, #ST_FCR_OFFSET]   @ Zero out FIFO Control Register
	str    r1,  [r0, #ST_LCR_OFFSET]   @ Zero out Line Control Register
	str    r1,  [r0, #ST_MCR_OFFSET]   @ Zero out Modem Control Register
	str    r1,  [r0, #ST_ISR_OFFSET]   @ Zero out IR bit register
	ldr    r1,  [r0, #ST_MSR_OFFSET]   @ Read MSR once to clear bits

	mov    r1,  #0x83	           @ Set up divisor latch bit (DLAB), 8 bit character, no parity, 1 stop bit
	str    r1,  [r0,  #ST_LCR_OFFSET]  @ Set DLAB bit

	str    r2,  [r0,  #ST_DLL_OFFSET]  @ set baud rate
	ldr    r1,  =0x0	           @ Insure high baud rate byte is zero
	str    r1,  [r0,  #ST_DLH_OFFSET]
	ldr    r1,  [r0,  #ST_LCR_OFFSET]  @ Get LCR values
	bic    r1,  r1,   #DLAB            @ Clear DLAB bit
	str    r1,  [r0,  #ST_LCR_OFFSET]  @ Write the value back out
	mov    r1,  #0x07	           @ This value will clear the TX and RX FIFOs
	str    r1,  [r0,  #ST_FCR_OFFSET]  @ ... and enabale the FIFOs for use.

	mov    r1,  #0x40	           @ set unit enable bit
	str    r1,  [r0,  #ST_IER_OFFSET]  @ enable the UART
	mov    pc, lr	                   @ Return to calling program

UartPrintStr:

        mov    r13, lr	         @ Save the link register value
next:
        ldrb   r2,  [r3],  #1    @ Place byte into r2 & increment pointer
        cmp    r2,  #0	         @ Is this byte NULL?
        beq    exit	         @ Yes - take exit path
        bl     UartPrintch	 @ No - Send byte out to UART
        b      next	         @ Get next byte
exit:
       mov    pc,  r13	         @ Return to the caller

UartPrintch:

bitset:
      ldr    r0,  = STUART_BASE_PHYSICAL
      ldr    r1,  [r0, #ST_LSR_OFFSET]	   @  Get Line Status Register Data
      ands   r1,  r1,  #TDRQ               @  Is TDRQ (Transmit Data Request) bit set?
      beq    bitset	                   @  No - loop until it is
      strb   r2,  [r0, #ST_THR_OFFSET]	   @  It's ready! - output byte to buffer
      mov    pc,  lr	                   @  Return to caller


@*********************************************************************************************
@
@ *************************************
@ **********                 **********
@ ********** CONFIGURE GPIOs **********
@ **********                 **********
@ *************************************
@
@ This subroutine sets up the GPIO pins in accordance with the values contained in the platform include file.
@
@ NOTES: Written for the PXA27x Processor on the Mainstone Development Platform.
@
Init_GPIO:

      ldr     r0,  =0x40E00000   			@ Load the GPIO register block base address
//      ldr     r1,  =0x8800              			@ Get the pin set values for GPSR0
      ldr 	r1, =0x02808800				@ //Bill 20060327
      str     r1,  [r0, #0x18]       				@ Write the GPSR0 values

//      ldr     r2,  =0x03cf0002              		@ Get the pin set values for GPSR1
      ldr     r2,  =0x03df0002              		@ Get the pin set values for GPSR1 //Bill 20060401
      str     r2,  [r0, #0x1c]       				@ Write the GPSR1 values

      ldr     r1,  =0x21fc00              		@ Get the pin set values for GPSR2
      str     r1,  [r0, #0x20]       				@ Write the GPSR2 values

      ldr     r2,  =0              				@ Get the pin set values for GPSR3
      str     r2,  [r0, #0x118]       			@ Write the GPSR3 values

      ldr     r1,  =0              				@ Get the pin clear values for GPCR0
      str     r1,  [r0, #0x24]       				@ Write the GPCR0 values

      ldr     r2,  =0              				@ Get the pin clear values for GPCR1
      str     r2,  [r0, #0x28]       				@ Write the GPCR1 values

      ldr     r1,  =0              				@ Get the pin clear values for GPCR2
      str     r1,  [r0, #0x2c]       				@ Write the GPCR2 values

      ldr     r2,  =0              				@ Get the pin clear values for GPCR3
      str     r2,  [r0, #0x124]       			@ Write the GPCR3 values

      ldr     r1,  =0xcbed6619              		@ Get the pin direction values for GPDR0
      str     r1,  [r0, #0x0c]       				@ Write the GPDR0 values

      ldr     r2,  =0xff32a9b3              		@ Get the pin direction values for GPDR1
      str     r2,  [r0, #0x10]       				@ Write the GPDR1 values

      ldr     r1,  =0x0bc5ffff              		@ Get the pin direction values for GPDR2
      str     r1,  [r0, #0x14]       				@ Write the GPDR2 values

      ldr     r2,  =0x006e1381              		@ Get the pin direction values for GPDR3
      str     r2,  [r0, #0x10c]       			@ Write the GPDR3 values

      ldr     r1,  =0x669c0000            		@ Get the pin alt function values for GAFR0_L
      str     r1,  [r0, #0x54]     				@ Write the GAFR0_L values

      ldr     r2,  =0xa5f00008            		@ Get the pin alt function values for GAFR0_U
      str     r2,  [r0, #0x58]     				@ Write the GAFR0_U values

      ldr     r1,  =0x69900e12            		@ Get the pin alt function values for GAFR1_L
      str     r1,  [r0, #0x5c]     				@ Write the GAFR1_L values

      ldr     r2,  =0xaaa07851            		@ Get the pin alt function values for GAFR1_U
      str     r2,  [r0, #0x60]     				@ Write the GAFR1_U values

      ldr     r1,  =0x02aaaaaa            		@ Get the pin alt function values for GAFR2_L
      str     r1,  [r0, #0x64]     				@ Write the GAFR2_L values

      ldr     r2,  =0x550cafc8            		@ Get the pin alt function values for GAFR2_U
      str     r2,  [r0, #0x68]     				@ Write the GAFR2_U values

      ldr     r1,  =0x565a95ff            		@ Get the pin alt function values for GAFR3_L
      str     r1,  [r0, #0x6c]     				@ Write the GAFR3_L values

      ldr     r2,  =0x00001409            		@ Get the pin alt function values for GAFR3_U
      str     r2,  [r0, #0x70]     		        @ Write the GAFR3_U values



@
@	The RDH and PH bits on PXA27x must be set to enable updated GPIO pins.
@       These are sticky bits.
@
      ldr     r0, =0x40F00000						@ set PMRCREGS PHYSICAL BASE
    mov     r2, #(0x10 | 0x20) 					@ Set the PH and RDH bits to enable all GPIOs
//      mov     r2, #0x0					@ Bill 20060326
      str     r2, [r0, #0x04]         			@ Enable all GPIO lines

/*
      ldr     r0,  =0x40E00000
      ldr     r2,  =0x59e5404e                          @ Get the pin alt function values for GAFR0_U
      str     r2,  [r0, #0x58]                                  @ Write the GAFR0_U values


      ldr     r2,  =0x20000
      str     r2,  [r0, #0x0]

      ldr     r2,  =0x20000
      str     r2,  [r0, #0xc]

      ldr     r2,  =0x28800
      str     r2,  [r0, #0x18]


*/

      mov     pc, lr                                    @ Return to calling program



@*********************************************************************************************
@*********************************************************************************************




Init_Mem:

	@  ***** STEP 1:	 *****
	@
	@  Delay 200 uS
	@
        ldr     r2,  =0x40A00000  @  Load OS timer base address
        ldr     r3,  [r2, #0x10]  @  Fetch starting value of OSCR0
        add     r3,  r3,  #0x300  @  Really 0x2E1 is about 200usec, so 0x300 should be plenty

//xlli_3:
//	ldr     r1,  [r2, #0x10]  @  Fetch current OSCR0 value
//	cmp     r1,  r3		  @  Is the timer past the time out value?
//	bmi     xlli_3		  @  No - Loop until it is
	mov r2, #0x10000
lop2:
    NOP
    sub r2, r2, #1
    cmp r2, #0
    bhi lop2
	@
	@   STEP 1 - 1st bullet:	 Write MSC0, MSC1 and MSC2 (the order is not important)
	@   *******************

	@
	@        Write the memory control registers
	@
        ldr     r4,  =0x48000000 @  Get memory controller base address

        ldr     r1,  =0x7ff87ff8 @  Set the value for MSC0
        str     r1,  [r4, #0x08] @  Write the value out
        ldr     r1,  [r4, #0x08] @  Read back to latch the data

        ldr     r2,  =0x0 @  Get MSC1 setting
        str     r2,  [r4, #0x0c] @  Write the value out
        ldr     r2,  [r4, #0x0c] @  Read back to latch the data

        ldr     r1,  =0x0 @  Get MSC2 setting
        str     r1,  [r4, #0x10] @  Write the value out
        ldr     r1,  [r4, #0x10] @  Read back to latch the data


	@
	@   STEP 1 - 2nd bullet:	 Write MECR, MCMEM0, MCMEM1, MCATT0, MCATT1, MCIO0, MCIO1 (order not important)
	@   *******************
	@
	@        (if required)

	@
	@   STEP 1 - 3rd bullet:	 Write FLYCNFG
	@   *******************
	@
        ldr     r1,  =0x00010001        @  write FLYCNFG
        str     r1,  [r4, #0x20]
	@

	@
	@   STEP 1 - 4th bullet:	 SKIPPED (used only when coming out of sleep)
	@   *******************
	@
	@      (If required, this would be a write to MDCNFG with enable bits deasserted.)

	@
	@   STEP 1 - 5th bullet:	 update MDREFR settings
	@   *******************
	@
        ldr     r2,  =0x23ca401e
        str     r2,  [r4, #0x04]


        ldr     r2,  =0x20ca201e
        str     r2,  [r4, #0x04]

	@
	@  Preserve MDREFR in r2
	@

	@  ***** STEP 2 *****
	@
	@  For systems with Synchronous Flash
	@
	@        Note:	 Synchronous Flash is handled in a separate xlli Functiona
	@

	@
	@  ***** STEP 3 *****
	@
	@  Clear the free run clock bits to enable the use of SDCLK for memory timing
	@
        ldr     r2,  =0x204b201e
        str     r2,  [r4, #0x04]

        ldr     r2,  =0x200b201e
        str     r2,  [r4, #0x04]
        ldr     r2,  =0x200ba01e
        str     r2,  [r4, #0x04]


        nop		@  Do not remove!
        nop		@  Do not remove!
	@
	@  ***** STEP 4 *****
	@
	@  Appropriately configure, but don't enable, each SDRAM partition pair
	@
        ldr     r1, =0x08c82a55	       @  Fetch platform value for MDCNFG

	bic     r1, r1,  #0x1
	bic	r1, r1,  #0x2
	bic     r1, r1,  #0x10000
	bic     r1, r1,  #0x20000
        @bic     r1, r1,  #(0x1 :	OR:	 0x2)      @  Disable all
        @bic     r1, r1,  #(0x10000 :	OR:	 0x20000)  @  SDRAM banks


        str     r1, [r4, #0x0]         @  Write w/o enabling SDRAM banks
	@
	@  ***** STEP 5 *****  (Delay at least 200 uS)
	@
	ldr     r2,  =0x40A00000       @  Load OS timer base address
	ldr     r3,  [r2, #0x10]       @  Fetch starting value of OSCR0
	add     r3,  r3,  #0x300       @  Really 0x2E1 is about 200usec, so 0x300 should be plenty
//xlli_5:
//	ldr     r1,  [r2, #0x10]       @  Fetch current OSCR0 value
//	cmp     r1,  r3	               @  Is the timer past the time out value?
//	bmi     xlli_5	               @  No - Loop until it is
	mov r2, #0x10000
lop3:
    NOP
    sub r2, r2, #1
    cmp r2, #0
    bhi lop3
	@
	@  ***** STEP 6 ***** (Make sure DCACHE is disabled)
	@
        mrc     p15, 0, r2, c1, c0, 0  @  load r2 contents of register 1 in CP 15
	bic     r2,  r2,  #0x04        @  Disable D-Cache
	mcr     p15, 0, r2, c1, c0, 0  @  Write back to CP15
	@
	@  ***** STEP 7 *****
	@
	@  Access memory *not yet enabled* for CBR refresh cycles (8)
	@  - CBR is generated for all banks
	@

//The following is added by Bill Chen
	/*******************     Step 7        ********************************/
	/*  Access memory *not yet enabled* for CBR refresh cycles (8)        */
	/*  - CBR is generated for all banks                                  */
//       ldr r0, =PWR_BASE_PHYSICAL
//	ldr r10, [r0, #RCSR_OFFSET]
//	mov	r2, #( RCSR_SLEEP_RESET + RCSR_GPIO_RESET)
//	tst     r10, r2
//	bne     12f                /* skip if sleep (or GPIO) reset. */
//The above is added by Bill Chen
//The following is modified by Bill Chen
#if 0
        ldr     r1, =0xa0000000
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]
	str     r1, [r1]

	str     r1, [r1]              @   Fix for erratum #116. Makes up for ineffective 1st mem access.
#endif

        ldr     r1, =0xa0000000
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]
	ldr     r0, [r1]

	ldr     r0, [r1]              @   Fix for erratum #116. Makes up for ineffective 1st mem access.
	@   This is being left in for PXA27x for the moment
	@
12:
	@  ***** STEP 8 *****
	@
	@   Re-enable D-cache if desired (we don't)

	@
	@  ***** STEP 9 *****
	@
	@  Re-enable SDRAM partitions
	@
        ldr     r2,  [r4, #0x0]	      @  Fetch the current MDCNFG value
	orr 	r2, r2, #0x80	      @ Bill Chen 20060213
        orr     r2,  r2,  #0x1        @  Enable SDRAM bank 0
        str     r2,  [r4, #0x0]	      @  Write back MDCNFG, enabling the SDRAM bank(s)
	@
	@  ***** STEP 10 *****
	@
	@  Write the MDMRS register to trigger an MRS command to all enabled banks of SDRAM.
	@
	@
	ldr     r1,  =0x0             @  Fetch platform MDMRS value
	str     r1,  [r4, #0x40]      @  Write the MDMRS value back
	@
	@  ***** STEP 11 *****
	@
	@  In systems with SDRAM or Synchronous Flash, optionally enable auto-power-down by setting MDREFR:	APD
	@
        ldr     r3,  [r4, #0x04]      @  Get MDREFR value
        orr     r3,  r3,  #0x00100000 @  enable auto power down
        str     r3,  [r4, #0x04]      @  Write value back

//The followign is added by Bill Chen 20060320
#if 0
	/***********************************************************************/
	/*******************      initialize the power manager  ****************/
	/***********************************************************************/
	ldr     r0,  =PWR_BASE_PHYSICAL
	mov		r1, #PCFR_OPDE		// 0 - Don't stop 13Mhz oscillator during standby, sleep or deep-sleep mode
						// 1 - Stop 13Mhz oscillator during standby, sleep or deep-sleep mode
#if 1
	orr		r1, r1, #PCFR_SYSEN_EN	// According to PXA270 Dev. Manual, it's reserved bit.
						// Does it have special feature ?
#endif
	str		r1, [r0, #PCFR_OFFSET]

#endif

	/*********************************************************************/
	/*        Check to see if we're coming out of sleep reset.           */
	/*           Read & Init Reset Cause bits in RCSR.                   */
	/* 	           r10 has reset case bits value			             */
	/*********************************************************************/

	ldr     r0,  =PWR_BASE_PHYSICAL
	ldr     r10, [r0, #RCSR_OFFSET]

	/* extract the reset cause bits */
#if 1	/*
	 * RCSR_ALL values was defined as 0x1F, But, it should be 0x0F
	 */
	mov     r2,  #RCSR_ALL		// Mask RCSR
#endif
	and     r10,  r10,  r2		// r10 now holds the conditioned Reset Reason

	/* clear the reset cause bits (they're sticky) */
	str     r2,  [r0, #RCSR_OFFSET]


	/************************************************************************/
	/*          if it's a sleep-reset, Jump back to the before sleep        */
	/*	                it might be Linux Kernel code				        */
	/************************************************************************/
	teq     r10, #RCSR_SLEEP_RESET
	bne     19f
	b       WakeUp

WakeUp:
	ldr	r1, =PWR_BASE_PHYSICAL
	ldr	r0, [r1, #PSPR_OFFSET]
//The following is commented  by Bill Chen 20060326
	nop
	nop
	nop
	nop
	nop
	mov     pc, r0
	nop
	nop
	nop
	nop

19:
        mov     pc, lr	              @  Return to calling program

//The above is added by Bill Chen 20060320

@ ******************************************************
@
@ NOTE: On system reset, all interrupts should be cleared by hardware.
@       This enforces disabling of all interrupts to HW boot default conditions.
@
Init_INT:

        ldr     r4,  =0x40d00000  				@ Load interrupt controller physical base address
        ldr     r2,  =0x0                                       @ zero out a work register
        str     r2,  [r4, #0x04]        			@ Mask all interrupts (clear mask register)
        str     r2,  [r4, #0xa0]       				@ Mask all interrupts (clear mask register) 2
        str     r2,  [r4, #0x08]        			@ Clear the interrupt level register
        str     r2,  [r4, #0xa4]       				@ Clear the interrupt level register 2
        str     r2,  [r4, #0x14]        			@ Clear Interrupt Control Register
        str     r2,  [r4, #0xa8]       				@ Clear Interrupt Control Register 2
        mov     pc,  lr                                         @ return to calling routine

@*********************************************************************************************
@*********************************************************************************************

@********************************************************************************************
@
@ **********************************************
@ **********                          **********
@ ********** INITIALIZE CLOCK MANAGER **********
@ **********                          **********
@ **********************************************
@
@ Disable the peripheral clocks, and set the core clock frequency
@
@ NOTE: The Change Frequency Sequence should be called after this function in order
@       for the clock frequencies set in the CCCR register to take effect.
@
@       The code then spins on the oscillator OK bit until the oscilator is stable
@       which can take as long as two seconds.
@

Init_Clocks:

@ Turn Off ALL on-chip peripheral clocks for re-configuration
@
        ldr     r4,  =0x41300000					@ Load clock registers base address
        ldr     r1,  =0x400000                  	@ Forces memory clock to stay ON!!
        ldr     r2,  =0x00400220           			@ Get any other bits required from the include file
        orr     r1,  r1,  r2                    	@ OR everything together
        str     r1,  [r4, #0x04]    				@ ... and write out to the clock enable register
@
@ Set Crystal: Memory Freq, Memory:RunMode Freq, RunMode, TurboMode Freq Multipliers,
@ set RunMode & TurboMode to default frequency.
@
        ldr     r2,  =0x00000110           			@ Get CORE_CLK_DEFAULT value
        str     r2,  [r4, #0x00]    				@ Write to the clock config register
@
@ Enable the 32 KHz oscillator and set the 32KHz output enable bits
@

        @mov     r1,  #(0x02 :OR: 0x04)
        mov	r1,  #0x6
	str     r1,  [r4, #0x08]    				@ for RTC and Power Manager
@
@ Init Real Time Clock (RTC) registers
@
        ldr     r4,  =0x40900000 					@ Load RTC registers base address
        mov     r2,  #0                          	@ Clear a work register
        str     r2,  [r4, #0x08]     				@ Clear RTC Status register
        str     r2,  [r4, #0x00]     				@ Clear RTC Counter Register
        str     r2,  [r4, #0x04]     				@ Clear RTC Alarm Register
        str     r2,  [r4, #0x28]     				@ Clear Stopwatch Counter Register
        str     r2,  [r4, #0x2c]    				@ Clear Stopwatch Alarm Register 1
        str     r2,  [r4, #0x30]    				@ Clear Stopwatch Alarm Register 2
        str     r2,  [r4, #0x34]     				@ Clear Periodic Counter Register
        str     r2,  [r4, #0x38]     				@ Clear Interrupt Alarm Register
@       mov     pc,  lr                          	@ DISABLED - Return here if A0 silicon
@
@ Check the Oscillator OK (OOK) bit in clock register OSCC to insure the timekeeping oscillator
@ is enabled and stable before returning to the calling program.
@
        ldr     r4,  =0x41300000					@ Reload clock registers base address
xlli_6:
        ldr     r1,  [r4, #0x08]    				@ Get the status of the OSCC register
        ands    r1,  r1,  #0x01        				@ is the oscillator OK bit set?
        beq     xlli_6                          	@ Spin in this loop until the bit is set



@
@ Frequence change
@ initiates the frequency change sequence
@ and restarts the memory controller
@

        mrc     p14, 0, r2, c6, c0, 0       		@ Get present status (preserve Turbo and Fast Bus bits)
        orr     r2,  r2,  #2                		@ Set the F bit
        mcr     p14, 0, r2, c6, c0, 0       		@ initiate the frequency change sequence - Wheeeeeeeee!
@
@       If the clock frequency is chaged, the MDREFR Register must be  rewritten, even
@       if it's the same value. This will result in a refresh being performed and the
@       refresh counter being reset to the reset interval. (Section 13.10.3, pg 13-17 of EAS)
@
        ldr     r4,  =0x48000000       				@ Get memory controller base address
        ldr     r1,  [r4, #0x04]      				@ Get the current state of MDREFR
        str     r1,  [r4, #0x04]      				@ Re-write this value


        mov     pc,  lr                             @ return to calling routine


@*********************************************************************************************
@*********************************************************************************************


xlli_setClocks:

	mov     pc, lr                              @ Return to calling program

@*********************************************************************************************
@*********************************************************************************************


xlli_freq_change:
	mov     pc, lr                              @ Return to calling program

@*********************************************************************************************
@*********************************************************************************************


/* Nam9, 2004. 9. 17 */

	.align 4
bss_start:	.word	__bss_start
bss_end	:	.word	__bss_end

@ addresses
blob_stack_pointer:	    .long   (0xA4000000 - 4)
blob_ram_base_addr:	    .long   0xA3C00000

	.align 2
str_init:	.ascii  "Init MEM CLOCK GPIO UART OK ... \n\r\x00"

	.align 2
str_cpspl:	       .ascii  "Copy Spl To Ram OK ... \n\r\x00"

	.align 2
str1:	       .ascii  "111111111111111 ... \n\r\x00"

	.align 2
str2:	          .ascii  "222222222222222 ... \n\r\x00"

	.align 2
str3:	          .ascii  "3333333333333333 ... \n\r\x00"

	.align 2
str4:	          .ascii  "44444444444444444 ... \n\r\x00"

	.align 4
	.set M_START, RAM_START
	.set M_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START, RAM_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START
	.set M_BOOT_LOADER_AREA_LENGTH, RAM_BOOT_LOADER_AREA_LENGTH
	.set M_STACK_END_OFFSET_FROM_RAM_START, RAM_STACK_END_OFFSET_FROM_RAM_START
